home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / cl_pred.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  6.3 KB  |  279 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. #include "client.h"
  22.  
  23.  
  24. /*
  25. ===================
  26. CL_CheckPredictionError
  27. ===================
  28. */
  29. void CL_CheckPredictionError (void)
  30. {
  31.     int        frame;
  32.     int        delta[3];
  33.     int        i;
  34.     int        len;
  35.  
  36.     if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
  37.         return;
  38.  
  39.     // calculate the last usercmd_t we sent that the server has processed
  40.     frame = cls.netchan.incoming_acknowledged;
  41.     frame &= (CMD_BACKUP-1);
  42.  
  43.     // compare what the server returned with what we had predicted it to be
  44.     VectorSubtract (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame], delta);
  45.  
  46.     // save the prediction error for interpolation
  47.     len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
  48.     if (len > 640)    // 80 world units
  49.     {    // a teleport or something
  50.         VectorClear (cl.prediction_error);
  51.     }
  52.     else
  53.     {
  54.         if (cl_showmiss->value && (delta[0] || delta[1] || delta[2]) )
  55.             Com_Printf ("prediction miss on %i: %i\n", cl.frame.serverframe, 
  56.             delta[0] + delta[1] + delta[2]);
  57.  
  58.         VectorCopy (cl.frame.playerstate.pmove.origin, cl.predicted_origins[frame]);
  59.  
  60.         // save for error itnerpolation
  61.         for (i=0 ; i<3 ; i++)
  62.             cl.prediction_error[i] = delta[i]*0.125;
  63.     }
  64. }
  65.  
  66.  
  67. /*
  68. ====================
  69. CL_ClipMoveToEntities
  70.  
  71. ====================
  72. */
  73. void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, trace_t *tr )
  74. {
  75.     int            i, x, zd, zu;
  76.     trace_t        trace;
  77.     int            headnode;
  78.     float        *angles;
  79.     entity_state_t    *ent;
  80.     int            num;
  81.     cmodel_t        *cmodel;
  82.     vec3_t        bmins, bmaxs;
  83.  
  84.     for (i=0 ; i<cl.frame.num_entities ; i++)
  85.     {
  86.         num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
  87.         ent = &cl_parse_entities[num];
  88.  
  89.         if (!ent->solid)
  90.             continue;
  91.  
  92.         if (ent->number == cl.playernum+1)
  93.             continue;
  94.  
  95.         if (ent->solid == 31)
  96.         {    // special value for bmodel
  97.             cmodel = cl.model_clip[ent->modelindex];
  98.             if (!cmodel)
  99.                 continue;
  100.             headnode = cmodel->headnode;
  101.             angles = ent->angles;
  102.         }
  103.         else
  104.         {    // encoded bbox
  105.             x = 8*(ent->solid & 31);
  106.             zd = 8*((ent->solid>>5) & 31);
  107.             zu = 8*((ent->solid>>10) & 63) - 32;
  108.  
  109.             bmins[0] = bmins[1] = -x;
  110.             bmaxs[0] = bmaxs[1] = x;
  111.             bmins[2] = -zd;
  112.             bmaxs[2] = zu;
  113.  
  114.             headnode = CM_HeadnodeForBox (bmins, bmaxs);
  115.             angles = vec3_origin;    // boxes don't rotate
  116.         }
  117.  
  118.         if (tr->allsolid)
  119.             return;
  120.  
  121.         trace = CM_TransformedBoxTrace (start, end,
  122.             mins, maxs, headnode,  MASK_PLAYERSOLID,
  123.             ent->origin, angles);
  124.  
  125.         if (trace.allsolid || trace.startsolid ||
  126.         trace.fraction < tr->fraction)
  127.         {
  128.             trace.ent = (struct edict_s *)ent;
  129.              if (tr->startsolid)
  130.             {
  131.                 *tr = trace;
  132.                 tr->startsolid = true;
  133.             }
  134.             else
  135.                 *tr = trace;
  136.         }
  137.         else if (trace.startsolid)
  138.             tr->startsolid = true;
  139.     }
  140. }
  141.  
  142.  
  143. /*
  144. ================
  145. CL_PMTrace
  146. ================
  147. */
  148. trace_t        CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
  149. {
  150.     trace_t    t;
  151.  
  152.     // check against world
  153.     t = CM_BoxTrace (start, end, mins, maxs, 0, MASK_PLAYERSOLID);
  154.     if (t.fraction < 1.0)
  155.         t.ent = (struct edict_s *)1;
  156.  
  157.     // check all other solid models
  158.     CL_ClipMoveToEntities (start, mins, maxs, end, &t);
  159.  
  160.     return t;
  161. }
  162.  
  163. int        CL_PMpointcontents (vec3_t point)
  164. {
  165.     int            i;
  166.     entity_state_t    *ent;
  167.     int            num;
  168.     cmodel_t        *cmodel;
  169.     int            contents;
  170.  
  171.     contents = CM_PointContents (point, 0);
  172.  
  173.     for (i=0 ; i<cl.frame.num_entities ; i++)
  174.     {
  175.         num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
  176.         ent = &cl_parse_entities[num];
  177.  
  178.         if (ent->solid != 31) // special value for bmodel
  179.             continue;
  180.  
  181.         cmodel = cl.model_clip[ent->modelindex];
  182.         if (!cmodel)
  183.             continue;
  184.  
  185.         contents |= CM_TransformedPointContents (point, cmodel->headnode, ent->origin, ent->angles);
  186.     }
  187.  
  188.     return contents;
  189. }
  190.  
  191.  
  192. /*
  193. =================
  194. CL_PredictMovement
  195.  
  196. Sets cl.predicted_origin and cl.predicted_angles
  197. =================
  198. */
  199. void CL_PredictMovement (void)
  200. {
  201.     int            ack, current;
  202.     int            frame;
  203.     int            oldframe;
  204.     usercmd_t    *cmd;
  205.     pmove_t        pm;
  206.     int            i;
  207.     int            step;
  208.     int            oldz;
  209.  
  210.     if (cls.state != ca_active)
  211.         return;
  212.  
  213.     if (cl_paused->value)
  214.         return;
  215.  
  216.     if (!cl_predict->value || (cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
  217.     {    // just set angles
  218.         for (i=0 ; i<3 ; i++)
  219.         {
  220.             cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[i]);
  221.         }
  222.         return;
  223.     }
  224.  
  225.     ack = cls.netchan.incoming_acknowledged;
  226.     current = cls.netchan.outgoing_sequence;
  227.  
  228.     // if we are too far out of date, just freeze
  229.     if (current - ack >= CMD_BACKUP)
  230.     {
  231.         if (cl_showmiss->value)
  232.             Com_Printf ("exceeded CMD_BACKUP\n");
  233.         return;    
  234.     }
  235.  
  236.     // copy current state to pmove
  237.     memset (&pm, 0, sizeof(pm));
  238.     pm.trace = CL_PMTrace;
  239.     pm.pointcontents = CL_PMpointcontents;
  240.  
  241.     pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]);
  242.  
  243.     pm.s = cl.frame.playerstate.pmove;
  244.  
  245. //    SCR_DebugGraph (current - ack - 1, 0);
  246.  
  247.     frame = 0;
  248.  
  249.     // run frames
  250.     while (++ack < current)
  251.     {
  252.         frame = ack & (CMD_BACKUP-1);
  253.         cmd = &cl.cmds[frame];
  254.  
  255.         pm.cmd = *cmd;
  256.         Pmove (&pm);
  257.  
  258.         // save for debug checking
  259.         VectorCopy (pm.s.origin, cl.predicted_origins[frame]);
  260.     }
  261.  
  262.     oldframe = (ack-2) & (CMD_BACKUP-1);
  263.     oldz = cl.predicted_origins[oldframe][2];
  264.     step = pm.s.origin[2] - oldz;
  265.     if (step > 63 && step < 160 && (pm.s.pm_flags & PMF_ON_GROUND) )
  266.     {
  267.         cl.predicted_step = step * 0.125;
  268.         cl.predicted_step_time = cls.realtime - cls.frametime * 500;
  269.     }
  270.  
  271.  
  272.     // copy results out for rendering
  273.     cl.predicted_origin[0] = pm.s.origin[0]*0.125;
  274.     cl.predicted_origin[1] = pm.s.origin[1]*0.125;
  275.     cl.predicted_origin[2] = pm.s.origin[2]*0.125;
  276.  
  277.     VectorCopy (pm.viewangles, cl.predicted_angles);
  278. }
  279.